/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.r.analysis.grr;

import com.google.common.collect.Lists;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.utils.ResourceBundleUtils;
import com.intelligent.ispc.constant.AppConstant;
import com.intelligent.ispc.core.dto.GrrAnalysisDataDto;
import com.intelligent.ispc.core.dto.GrrParamDto;
import com.intelligent.ispc.core.dto.GrrSummaryDto;
import com.intelligent.ispc.r.analysis.RCommand;
import com.intelligent.ispc.r.utils.REnConnector;
import com.intelligent.ispc.r.utils.RUtils;
import org.rosuda.JRI.REXP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Created by Peter on 2015/12/10.
 */
public class GrrSummaryCommand implements RCommand {
    private static Logger logger = LoggerFactory.getLogger(GrrSummaryCommand.class);

    private String scriptPath = "";
    private GrrParamDto grrParamDto;
    private GrrConfiguration configuration;
    private List<GrrAnalysisDataDto> analysisParams;
    private List<GrrSummaryDto> resultData = Lists.newArrayList();

    private double operator = 0D;
    private double parts = 0D;
    private double trial = 0D;
    private double sigma = 0D;

    private String grrName;

    /**
     * @param scriptPath the file path
     */
    public GrrSummaryCommand(String scriptPath) {
        this.scriptPath = scriptPath;
    }

    protected void buildScript() {
        try {
            REnConnector con = RUtils.getInstance().getConnector();

            operator = Double.parseDouble(grrParamDto.getOperatorValue());
            parts = Double.parseDouble(grrParamDto.getPartValue());
            trial = Double.parseDouble(grrParamDto.getTrialValue());
            sigma = Double.parseDouble(grrParamDto.getSigma());

            //projectId = (String) params.get(Constant.GLOBAL_PROJECT_ID);
            grrName = grrParamDto.getGrrName();

            String dataSettings = getDataSettings(analysisParams, con);

            con.setInput("build", dataSettings);
            con.setInput("bitNum", grrParamDto.getDigitNum());
            con.setInput("funName", "summary <- grr.buildSummary(items)");
            con.execEval("source(\"" + scriptPath + "\")");

            /*con.setOutput("summary", RDataObjectType.Double2DArray);
            con.execute();*/

            this.buildResultData(analysisParams, con);
            while (con.isActive()) {
                con.disconnect();
            }
            RUtils.getSemaphore().release();


        } catch (Exception ex) {
            throw new ApplicationException(ExceptionMessages.ERR_20001, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_SYSTEM));
        }
    }


    private String getDataSettings(List<GrrAnalysisDataDto> dtoList, REnConnector con) {
        StringBuilder sb = new StringBuilder();
        sb.append("items <- grr.buildData(");

        int i = 1;
        for (GrrAnalysisDataDto dto : dtoList) {
            double usl = Double.valueOf(dto.getUsl());
            double lsl = Double.valueOf(dto.getLsl());
            double tole = Double.valueOf(AppConstant.GLOBAL_NAN);
            if (!Double.isNaN(usl) && !Double.isNaN(lsl)) {
                tole = usl - lsl;
            }
            con.setInput("x" + i, dto.getAnalysisData());
            sb.append("list(data=x" + i + ",")
                    .append("appraisers=" + operator + ",")
                    .append("parts=" + parts + ",")
                    .append("trials=" + trial + ",")
                    .append("sigma=" + sigma + ",")
                    .append("tole=" + tole + "),");
            i++;
        }
        sb.delete(sb.lastIndexOf(","), sb.length());
        sb.append(")");

        return sb.toString();
    }

    private void buildResultData(List<GrrAnalysisDataDto> dtoList, REnConnector con) {
        REXP expression = con.getEval("summary");
        double[][] summaryData = null;
        if (expression != null) {
            summaryData = expression.asDoubleMatrix();
        }
        if (summaryData != null) {
            for (int i = 0; i < dtoList.size(); i++) {
                GrrSummaryDto summaryDto = new GrrSummaryDto();

                //summaryDto.setProjectId(projectId);
                summaryDto.setGrrName(grrName);
                //summaryDto.setStationAndSlot(stationAndSlot);

                summaryDto.setItemName(dtoList.get(i).getItemName());
                //tole, PV, TV, GRR
                summaryDto.setTolerance(String.valueOf(configuration.getDataValue(summaryData[i][0] + "")));
                summaryDto.setUsl(String.valueOf(dtoList.get(i).getUsl()));
                summaryDto.setLsl(String.valueOf(dtoList.get(i).getLsl()));
                if (dtoList.get(i).isInvalidate()) {
                    summaryDto.setPartVariation("-");
                    summaryDto.setTotalProcessVariation("-");
                    summaryDto.setGrr("-");
                    summaryDto.setResult(configuration.getLevelType(Double.valueOf("Infinity")));
                } else {
                    summaryDto.setPartVariation(String.valueOf(configuration.getDataValue(summaryData[i][1] + "")));
                    summaryDto.setTotalProcessVariation(String.valueOf(configuration.getDataValue(summaryData[i][2] + "")));
                    summaryDto.setGrr(String.valueOf(configuration.getDataValue(summaryData[i][3] + "")));
                    summaryDto.setResult(configuration.getLevelType(summaryData[i][3]));
                }
                this.resultData.add(summaryDto);
            }
        }
    }

    @Override
    public void execute() {
        buildScript();
    }


    public String getScriptPath() {
        return scriptPath;
    }

    public void setScriptPath(String scriptPath) {
        this.scriptPath = scriptPath;
    }

    public GrrParamDto getGrrParamDto() {
        return grrParamDto;
    }

    public void setGrrParamDto(GrrParamDto grrParamDto) {
        this.grrParamDto = grrParamDto;
    }

    public GrrConfiguration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(GrrConfiguration configuration) {
        this.configuration = configuration;
    }

    public List<GrrAnalysisDataDto> getAnalysisParams() {
        return analysisParams;
    }

    public void setAnalysisParams(List<GrrAnalysisDataDto> analysisParams) {
        this.analysisParams = analysisParams;
    }

    public List<GrrSummaryDto> getResultData() {
        return resultData;
    }

    public void setResultData(List<GrrSummaryDto> resultData) {
        this.resultData = resultData;
    }
}
